/* @Description:utils/libModel.ts @author:378237242@qq.com @date:2023/11/3 */
import {
  hasCommonElements,
  findCommonElement,
  hasFalse,
  excludePrivateProperties,
} from "./utils";
import { cloneDeep, zip } from "lodash";

type AnalysisResult = {
  word: string[];
  pos: string[];
  dp: { parent: number; relate: string }[];
};
// _开头是私有成员，最后返回模版时会排除
type Model = {
  name: string;
  cname: string;
  // 关键字数组，主要是动作
  _actionKeywords: string[];
  // 关键词匹配策略 命名方式必须是 _关键词Rule
  _actionKeywordsRule: (analysisResult: AnalysisResult) => boolean;
  // 简单动宾结构宾语
  _targetKeywords: string[];
  _targetKeywordsRule: (analysisResult: AnalysisResult) => boolean;
  // 参数构造
  paramsStructure: Array<Record<string, string>>;
  [key: string]: any;
};
// 定义一个意图模型数组
const Models: Model[] = [
  {
    name: "pipelineQueries",
    cname: "管线查询",
    // 关键字数组，主要是动作
    _actionKeywords: ["查询", "查", "查寻"],
    _actionKeyword: {},
    _actionKeywordsRule: function (analysisResult: AnalysisResult) {
      // 1.判断分词结果必须存在关键词
      // 2.关键词必须是动词v,必须是核心或直接宾语
      const keyword = findCommonElement(
        this._actionKeywords,
        analysisResult.word,
      );
      if (keyword) {
        const { indexInB } = keyword;
        if (
          analysisResult.pos[indexInB] === "v" &&
          (analysisResult.dp[indexInB].relate === "HED" ||
            analysisResult.dp[indexInB].relate === "VOB")
        ) {
          this._actionKeyword = keyword;
          return true;
        } else {
          return false;
        }
      } else {
        return false;
      }
    },
    // 简单动宾结构宾语
    _targetKeywords: ["管线"],
    _targetKeyword: {},
    _targetKeywordsRule: function (analysisResult: AnalysisResult) {
      const keyword = findCommonElement(
        this._targetKeywords,
        analysisResult.word,
      );
      if (keyword) {
        const { indexInB } = keyword;
        if (
          analysisResult.pos[indexInB] === "n" &&
          (analysisResult.dp[indexInB].relate === "ATT" ||
            analysisResult.dp[indexInB].relate === "VOB")
        ) {
          this._targetKeyword = keyword;
          return true;
        } else {
          return false;
        }
      } else {
        return false;
      }
    },
    // 参数构造
    paramsStructure: [
      { name: "location", cname: "位置", value: "" },
      { name: "space", cname: "空间", value: "" },
    ],
    _paramsStructure: function (analysisResult: AnalysisResult) {
      const allATT = zip(
        analysisResult.word,
        analysisResult.pos,
        analysisResult.dp,
      )
        .slice(this._actionKeyword.indexInB, this._targetKeyword.indexInB)
        .filter((w) => {
          return w[2].relate === "ATT";
        });
      const arrTemp1 = allATT.filter((w) => {
        return w[1] !== "nl";
      });
      const arrTemp2 = allATT.filter((w) => {
        return w[1] === "nl";
      });
      this.paramsStructure[0].value = arrTemp1.map((m) => m[0]).join("");
      this.paramsStructure[1].value = arrTemp2.map((m) => m[0]).join("");
    },
  },
];

// 模型匹配策略:遍历模型数组，如果策略数组中有一个策略的模型规则返回false，则返回null，否则返回排除私有属性的模型
const matchModel = (analysisResult: AnalysisResult, strategyArr: string[]) => {
  for (const Model of Models) {
    const ModelTemp = cloneDeep(Model);
    if (
      hasFalse(strategyArr.map((a) => ModelTemp[`_${a}Rule`](analysisResult)))
    ) {
      return null;
    } else {
      // ModelTemp 命中模型
      // 构造模型参数
      ModelTemp._paramsStructure(analysisResult);
      return excludePrivateProperties(ModelTemp);
    }
  }
};

export { matchModel, AnalysisResult };
